import { messageTransfer } from '../messaging/MessageTransfer'
import BaseStation from './BaseStation'
import Product from './Product'
import SimulationSpeed from '../core/SimulationSpeed'
import { addReadyProduct, getReadyProduct } from '../core/ReadyProducts'
import { currentTime } from '../core/SimulationClock'
import { schedule } from '../core/Scheduler'

class BatchProcess extends BaseStation {
  //批处理数量
  batchQuantity: number
  //批处理时间
  processTime: number
  //动画方向
  animationDirection: 'left' | 'right' | 'up' | 'down'
  //起点和终点
  path: { startX: number; startY: number; endX: number; endY: number } = {
    startX: 0,
    startY: 0,
    endX: 0,
    endY: 0
  }
  //移动距离
  moveDistance: number = 0
  //产品序列
  processingProduct: Product[] = []
  //已加工完毕产品
  finishProduct: Product[] = []

  constructor(
    id: string,
    name: string,
    x: number,
    y: number,
    width = 100,
    height = 100,
    batchQuantity: number,
    processTime: number,
    animationDirection: 'left' | 'right' | 'up' | 'down'
  ) {
    super(id, name, x, y, width, height)
    this.batchQuantity = batchQuantity
    this.processTime = processTime
    this.animationDirection = animationDirection

    let initX = 0
    let initY = 0
    if (this.animationDirection === 'left') {
      initX = this.x
      initY = this.y + this.height / 2
    } else if (this.animationDirection === 'right') {
      initX = this.x + this.width
      initY = this.y + this.height / 2
    } else if (this.animationDirection === 'up') {
      initX = this.x + this.width / 2
      initY = this.y
    } else if (this.animationDirection === 'down') {
      initX = this.x + this.width / 2
      initY = this.y + this.height
    }
    this.path.startX = initX
    this.path.startY = initY

    let targetX = 0
    let targetY = 0
    if (this.animationDirection === 'left') {
      targetX = this.x + this.width
      targetY = this.y + this.height / 2
    } else if (this.animationDirection === 'right') {
      targetX = this.x
      targetY = this.y + this.height / 2
    } else if (this.animationDirection === 'up') {
      targetX = this.x + this.width / 2
      targetY = this.y + this.height
    } else if (this.animationDirection === 'down') {
      targetX = this.x + this.width / 2
      targetY = this.y
    }
    this.path.endX = targetX
    this.path.endY = targetY

    if (this.animationDirection === 'left' || this.animationDirection === 'right') {
      this.moveDistance = this.width
    } else {
      this.moveDistance = this.height
    }

    this.handlerResidualProduct()
  }

  public canReceiveProduct(): boolean {
    return this.processingProduct.length + this.finishProduct.length < this.batchQuantity
  }

  receiveReadyProduct(productId: string): void {
    this.readyProduct = productId

    const product = getReadyProduct(productId)
    if (!product) {
      this.setStatus('idle')
      console.log(`[${currentTime}] ❌ ${productId} 没有发现`)
      return
    }
    console.log(`[${currentTime}] ${product.id} 已到达 --> ${this.id}`)

    product.setFrom(this.id)
    this.onProductReceived(product)
  }

  onProductReceived(product: Product): void {
    messageTransfer('product', 'transport', {
      targetId: this.id,
      productId: product.id,
      x: this.path.startX,
      y: this.path.startY,
      duration: 0
    })
    messageTransfer('product', 'startProcessing', { targetId: this.id, productId: product.id })
    this.processingProduct.push(product)

    //算出移动时间
    const duration = this.processTime / SimulationSpeed.getSpeed
    messageTransfer('product', 'transport', {
      targetId: this.id,
      productId: product.id,
      x: this.path.endX,
      y: this.path.endY,
      duration: duration
    })
    messageTransfer('style', null, {
      targetId: this.id,
      style: {
        quantity: this.processingProduct.length + this.finishProduct.length
      }
    })
    schedule(
      this.processTime,
      () => {
        this.finishProcessing(product)
      },
      'Product processing completed'
    )
  }

  //完成加工
  finishProcessing(product: Product) {
    // 查找正在加工的产品列表中与传入产品ID匹配的索引
    const productIndex = this.processingProduct.findIndex((p) => p.id === product.id)
    if (productIndex !== -1) {
      //移除正在加工的产品
      this.processingProduct.splice(productIndex, 1)

      messageTransfer('product', 'finishProcessing', { targetId: this.id, productId: product.id })
      this.finishProduct.push(product)

      //向下游派发产品
      this.tryDispatchCurrentProduct(product)

      messageTransfer('style', null, {
        targetId: this.id,
        style: {
          quantity: this.processingProduct.length + this.finishProduct.length
        }
      })

      //向上游索要产品
      this.setStatus('processing')
      this.setStatus('idle')
    }
  }

  //向下游派发产品
  public tryDispatchCurrentProduct(pointerProduct?: Product): void {
    if (this.finishProduct.length === 0) return

    for (const next of this.nextStations) {
      if (this.finishProduct.length === 0) return

      const product = pointerProduct || this.finishProduct[0]
      if (next.canReceiveProduct(this.id, product)) {
        const product = this.finishProduct.shift()
        if (!product) return
        addReadyProduct(product)
        next.receiveReadyProduct(product.id)
      }
    }
  }

  //一个兜底策略，检测已加工完毕的产品，然后推给下游
  private handlerResidualProduct() {
    setInterval(() => {
      this.tryDispatchCurrentProduct()
    }, 10000)
  }
}

export default BatchProcess
